#include <iostream>
#include <string>
#include <typeinfo>

class Any
{
private:
    class holder
    {
    public:
        holder()
        {
        }

        virtual ~holder()
        {
        }

        // 都是纯虚函数，迫使子类重写
        virtual const std::type_info &type() = 0;

        // 将来Any对象有可能进行拷贝构造，所以子类还能够克隆出一个新的对象
        virtual holder *clone() = 0;
    };

    template <class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T &val)
            : _val(val)
        {
        }

        virtual ~placeholder()
        {
        }

        virtual const std::type_info &type()
        {
            return typeid(T);
        }

        virtual holder *clone()
        {
            return new placeholder(_val);
        }

    public:
        T _val; // 子类真正用于保存数据
    };

public:
    Any()
        : _content(nullptr)
    {
    }

    ~Any()
    {
        if (_content)
            delete _content;
    }

    // 模板函数，参数是任意类型，可以接收任意类型的数据
    // 通过特定类型数据创建Any对象
    template <class T>
    Any(const T &val)
        : _content(new placeholder<T>(val))
    {
    }

    // 通过其他Any对象创建一个新的Any对象
    Any(const Any &other)
        : _content(other._content == nullptr ? nullptr : other._content->clone())
    {
    }

    // 获取子类placeholder中保存的数据的指针
    template <class T>
    T *get()
    {
        if (typeid(T) != _content->type())
            return nullptr;
        return &((placeholder<T> *)_content)->_val;
    }

    // 赋值运算符重载
    template <class T>
    Any &operator=(const T &val)
    {
        Any tmp(val);
        std::swap(_content, tmp._content);
        return *this;
    }

    Any &operator=(Any other)
    {
        std::swap(_content, other._content);
        return *this;
    }

private:
    holder *_content;
};

class Test
{
public:
    Test() { std::cout << "构造" << std::endl; }
    Test(const Test &t) { std::cout << "拷贝构造" << std::endl; }
    ~Test() { std::cout << "析构" << std::endl; }
};

int main()
{
    // int a = 10;
    // const std::type_info &t = typeid(int);

    Any any;
    any = 10;
    int *pa = any.get<int>();
    std::cout << *pa << std::endl;

    any = 10.24;
    double *pd = any.get<double>();
    std::cout << *pd << std::endl;

    any = std::string("hello");
    std::string *ps = any.get<std::string>();
    std::cout << *ps << std::endl;

    // 测试是否存在内存泄露
    {
        any = Test();
    }

    return 0;
}